package com.example.birdfriends.utils.export;

import com.example.birdfriends.pojo.export.ExcelHeaderCell;
import com.sun.javafx.scene.SceneEventDispatcher;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFDataFormat;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;

public class ExcelWriteUtil {
    // 单个sheet的最大数据条数
    private static final int MAX_SINGLE_SHEET_NUM = 10000;
    private BufferedOutputStream outputStream;
    private List<ExcelHeaderCell> headerCells;
    private SXSSFWorkbook sxssfWorkbook;
    private SXSSFSheet sxssfSheet;
    private CellStyle cellStyle;
    // 当前工作表索引
    private int currentSheetIndex = 0;
    // 当前行索引
    private int currentRowIndex = 0;
    // 单元格索引
    private int cellIndex = 0;

    public ExcelWriteUtil(String filePath, List<ExcelHeaderCell> headerCells){
        this.headerCells = headerCells;
        init(filePath);
    }

    private void init(String filePath){
        try {
            sxssfWorkbook = new SXSSFWorkbook(this.getSXSSfWorkbook(filePath), 1000);
            cellStyle = getAndSetXSSFCellStyle(sxssfWorkbook);
            outputStream = new BufferedOutputStream(Files.newOutputStream(Paths.get(filePath)));
            headerWrite();
        }catch (Exception e){
            close();
            throw new RuntimeException("文件初始化失败！"+e.getMessage());
        }
    }

    // 创建XSSFWorkbook对象
    private XSSFWorkbook getSXSSfWorkbook(String filePath){
        BufferedOutputStream stream = null;
        XSSFWorkbook workbook = null;
        try{
            File excelFilePath = new File(filePath);
            if(!excelFilePath.getParentFile().exists()) {
                excelFilePath.getParentFile().mkdirs();
            }
            stream = new BufferedOutputStream(Files.newOutputStream(excelFilePath.toPath()));
            workbook = new XSSFWorkbook();
            workbook.write(stream);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }finally {
            if(stream != null){
                try{
                    stream.close();
                }catch (IOException e){
                    throw new RuntimeException(e.getMessage());
                }
            }
        }

        return workbook;
    }

    private CellStyle  getAndSetXSSFCellStyle(SXSSFWorkbook sxssfWorkbook){
        XSSFCellStyle xssfCellStyle = (XSSFCellStyle) sxssfWorkbook.createCellStyle();
        XSSFDataFormat dataFormat = (XSSFDataFormat) sxssfWorkbook.createDataFormat();

        xssfCellStyle.setWrapText(false);
        xssfCellStyle.setAlignment(HorizontalAlignment.CENTER);
        xssfCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        xssfCellStyle.setDataFormat(dataFormat.getFormat("0"));

        return xssfCellStyle;
    }

    // 写入表头
    private void headerWrite() {
        sxssfSheet = sxssfWorkbook.createSheet("sheet"+currentSheetIndex);
        sxssfSheet.setDefaultColumnWidth(50);
        SXSSFRow row = sxssfSheet.createRow(currentRowIndex);
        headerCells.forEach(item -> {
            SXSSFCell cell = row.createCell(cellIndex);
            cell.setCellStyle(cellStyle);
            cell.setCellType(CellType.STRING);
            cell.setCellValue(item.getColumnName());
            cellIndex++;
        });
        currentRowIndex++;
    }

    //写入数据
    public void writeBatch(List<Map<String, Object>> data){
        try{
            for(Map<String, Object> map: data){
                if(currentRowIndex == 0){  // 行索引号为0，需要初始化一个sheet
                    sxssfSheet = sxssfWorkbook.createSheet("sheet"+currentSheetIndex);
                    sxssfSheet.setDefaultColumnWidth(50);
                }
                SXSSFRow row = sxssfSheet.createRow(currentRowIndex);
                cellIndex = 0;  // 单元格索引
                for (ExcelHeaderCell headerCell: headerCells){
                    SXSSFCell cell = row.createCell(cellIndex);
                    cell.setCellType(CellType.STRING);
                    cell.setCellStyle(cellStyle);
                    Object val = map.get(headerCell.getColumnCode());
                    if(val == null){
                        cell.setCellValue("");
                    }else {
                        cell.setCellValue(val.toString());
                    }
                    cellIndex ++;
                }
                if(currentRowIndex == MAX_SINGLE_SHEET_NUM){
                    currentRowIndex = 0;
                    currentSheetIndex++;
                }else {
                    currentRowIndex++;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    // 刷新
    public void flush(){
        try{
            sxssfWorkbook.write(outputStream);
            outputStream.flush();
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }finally {
            close();
        }
    }

    // 关闭资源
    public void close(){
        if(outputStream != null){
            try {
                outputStream.close();
            }catch (Exception e){
                e.printStackTrace();
                throw new RuntimeException("关闭流文件失败！"+e.getMessage());
            }
        }
        if (sxssfWorkbook != null){
            sxssfWorkbook.dispose();
        }
    }
}
